#include "CryptString.h"
#include <QCryptographicHash>
#include <QByteArray>
#include <QDateTime>
#include <QString>
CryptString::CryptString(const QString &data)
    :_data(data)
{}

QString CryptString::generateMD5() const
{
    QByteArray arr=_data.toUtf8();

    QByteArray md5Result=QCryptographicHash::hash(arr,QCryptographicHash::Md5);

    return md5Result.toHex();
}

KVQuery::KVQuery()
{
    _map.insert(std::make_pair("secret","f6fdffe48c908deb0f4c3bd36c032e72"));

    QDateTime currentDateTime = QDateTime::currentDateTime();
    string secstr = std::to_string(currentDateTime.toSecsSinceEpoch());
    _map.insert(std::make_pair("t", secstr));

}


void KVQuery::add (const std::string &key,const std::string &value)
{
    _map.insert(std::make_pair(key,value));
}

void KVQuery::erase(const std::string &key)
{
    _map.erase(key);
}

void KVQuery::clear()
{
    _map.clear();
}

//**
// * @brief 将键值对转换为URL查询字符串的实现
// * @return 格式为"key1=value1&key2=value2..."的字符串
// * @details 1. 遍历map中的所有键值对
// *          2. 拼接成"key=value&"的格式
// *          3. 移除最后一个多余的"&"
// */
string KVQuery::toString() const
{
    string tmp; // 临时字符串，用于拼接结果

    // 遍历map中的每个键值对（map会按key自动排序）
    for (auto &elem : _map) {
        // 拼接格式：key=value&
        tmp.append(elem.first)    // 拼接键名
           .append("=")           // 拼接等号
           .append(elem.second)   // 拼接键值
           .append("&");          // 拼接分隔符
    }

    // 移除最后一个多余的"&"（如果map不为空）
    if (!tmp.empty()) {
        tmp.pop_back();
    }

    return tmp;
}

//*
// * @brief 生成包含加密令牌的查询字符串的实现
// * @return 包含token且不含secret的URL查询字符串
// * @details 流程：
// *          1. 将当前键值对（含secret和t）转换为字符串
// *          2. 对该字符串生成MD5哈希值作为token
// *          3. 将token添加到键值对中
// *          4. 移除secret字段（不在URL中传输）
// *          5. 转换为最终的查询字符串

string KVQuery::toCrpyString()
{
    // 1. 将当前键值对（含secret和t）转换为字符串，用于生成token
    string plainText = toString();

    // 2. 使用CryptString生成该字符串的MD5哈希值作为token
    CryptString cryptStr(QString::fromStdString(plainText));
    QString token = cryptStr.generateMD5();

    // 3. 将token添加到键值对中
    this->add("token", token.toStdString());

    // 4. 移除secret字段（secret仅用于生成token，不随URL传输）
    this->erase("secret");

    // 5. 转换为最终的查询字符串并返回
    return toString();
}


